//	nexys3_bot_if.v - Register interface to the between RojoBot world and Application Program 
//	
//	Copyright Aditya Joshi, Ajunja Vaidya(2014)
//
//	Created By:			Aditya Joshi, Anuja Vaidya
//	Created On:			28-Apr-2014 (AJ)
//	
//	Description
//	-----------
//	This module implements a register-based interface to the Application Program.
//	The Rojobot is implemented in a SOC embedded system using the Xilinx
//	Picoblaze as the CPU and block of logic (in verilog) to implement the world map.
//	  
//	A Rojobot-based system design needs access to information about the location of
//	the Rojobot in its simulated world.  This access is in the form of the following
//	8-bit registers:
//			Loc_X		O	X (column) coordinate of Rojobot's current location
//			Loc_y		O 	Y (row) coordinate of Rojobot's current location
//			Sensors		O	Sensor values.  Rojobot contains a proximity sensor (left and right)
//						 	A proximity sensor is set to 1 if Rojobot detects an object in
//						  	front of it.  It also contains a black line sensor (left, center
//						  	and right).  Each black line sensor is set to 0 if there is
//							a black line under it and set to 1 if there is not black line
//							under it.
//			BotInfo		O 	Information on rojobot's current orientation and movement
//
//	
//	Data from the BOTSIM is stored in internal registers
//	as they are written by the PicoBlaze.  The Rojobot interface provides a synchronized
//	view of all of the registers by transferring the contents of the internal registers when
//	internal control signals are asserted by the PicoBlaze by writing the following port addresses:
//		PRW_LOADREGS,	Port Address 0C		; loads system interface registers
//		PRW_LDMOTDIST,  Port Address 0D		; loads motor distance counters
//		PRW_RUNNING,	Port Address 0E		; a way for the PicoBlaze program to indicate it's running
//		Each write to the specific port toggles the control signal (which is reset to deasserted)		  					
//////////

module nexys3_bot_if (
    // interface to the BotSim world
	input [7:0] loc_x,					// X-coordinate of rojobot's location
	input [7:0] loc_y,                  // Y-coordinate of rojobot's location
	input [7:0] bot_info,               // Rojobot orientation and movement
	input [7:0] sensors,                // Sensor readings
	input [7:0] Lm_dist,                // Left motor distance register
	input [7:0] Rm_dist,                // Right motor distance register
	input upd_sysregs,					// flag from PicoBlaze to indicate that the system registers
										// (LocX, LocY, Sensors, BotInfo)have been updated	
	output reg [7:0] motctl,			// Motor control output
	
	// interface to the Application Progam (PicoBlaze)
	input [7:0] port_id,				// I/O port address
	input [7:0] out_port,				// Data to be written to I/O register
	input write_strobe,					// Write strobe - asserted to write I/O data
	input read_strobe,					// Read strobe - asserted to read I/O data
	input interrupt_ack,
	output reg [7:0] in_port,			// I/O register data to picoblaze
	output reg interrupt,   
	
	// interface to seven-segment module
	output reg [4:0] dig3,				// digit3 to be displayed
	output reg [4:0] dig2,				// digit2 to be displayed
	output reg [4:0] dig1,				// digit1 to be displayed
	output reg [4:0] dig0,				// digit0 to be displayed
	output reg [3:0] decpt,				// decimal point to be displayed
	
	// interface to debounce module
	input [7:0] db_sw,					// input press-buttons
	input [4:0] db_btns,				// debounced output
	
	// interface to LED module
	output reg [7:0] LED,				// data to display on LED
	
	// System clock & reset
	input clk,
	input reset
);

// interrupt flip flop to latch upd_sysregs flag properly
always @(posedge clk) 
    begin
		if (interrupt_ack == 1)
			interrupt <= 0;
		else begin
			if (upd_sysregs == 1)
				interrupt <= 1;
			else
				interrupt <= interrupt;
			end;
        //end if;
    end;

	 // read registers
always @(*) begin
	case (port_id[3:0])
	// IO registers serving read requests by Application Program
		4'b1010 :	in_port <= loc_x;								// Read request for LocX value
		4'b1011 :	in_port <= loc_y;								// Read request for LocY value
		4'b1100 :	in_port <= bot_info;							// Read request for BotInfo value
		4'b1101 :	in_port <= sensors;								// Read request for Sensors value
		4'b0001 :	in_port <= db_sw;								// Read request for debounce switches value
		4'b0000 :	in_port <= {3'b000,db_btns[0],db_btns[4:1]};	// Read request for debounce push-buttons value
		4'b1110 :   in_port <= Lm_dist;								// Read request for LM_Dist value
		4'b1111 :   in_port <= Rm_dist;								// Read request for RM_Dist value
		//4'b0111 :   in_port <= {4'b0000,decpt};
	endcase
end // always - read registers


// write registers
always @(posedge clk or posedge reset) begin
	if (reset) begin
	// On reset, set all values to 0
		motctl <= 0;
		//interrupt <= 0;
		dig3 <= 0;
		dig2 <= 0;
		dig1 <= 0;
		dig0 <= 0; 
		decpt<= 0;
		LED <= 0;
	end
	else if(write_strobe) begin
			case (port_id[3:0])
			// based on port-write request by Application Program, output the data
				// I/O registers for rojobot simulator HW interface
				4'b1001 :    motctl <= out_port	;				// Port 09 for motor control
				//4'b00XX :	 interrupt  <=  out_port;			
				4'b0011 :    dig3  <= out_port[4:0];			// Port 03 for digit3 of seven-seg display
				4'b0100 :	 dig2  <= out_port[4:0];			// Port 04 for digit2 of seven-seg display	 
				4'b0101 :	 dig1  <= out_port[4:0];			// Port 05 for digit1 of seven-seg display
				4'b0110 :    dig0  <= out_port[4:0];	 		// Port 06 for digit0 of seven-seg display
				4'b0111 : 	 decpt <= out_port[3:0];			// Port 07 for decimal points of seven-seg display
				4'b0010 :	 LED   <= out_port;					// Port 02 for LEDs
			endcase
		end
	else begin // refresh registers
		dig3       <=dig3    ;
		dig2       <=dig2    ;
		dig1       <=dig1    ;
		dig0       <=dig0    ;
		decpt      <=decpt   ;
		motctl     <=motctl  ;
		//interrupt  <=interrupt ;
		LED        <=LED    ;  
	end
end // always - write registers

endmodule